package com.lwc.cfdns.interceptor;

import com.lwc.cfdns.config.JwtConfig;
import com.lwc.cfdns.constants.Constants;
import com.lwc.cfdns.exception.AuthException;
import com.lwc.cfdns.enums.ResultCode;
import com.lwc.cfdns.constants.ConstantsUrl;
import com.lwc.cfdns.exception.BadException;
import com.lwc.cfdns.utils.ApiSignUtils;
import com.lwc.cfdns.utils.JwtUtils;
import com.lwc.cfdns.utils.RedisUtils;
import com.lwc.cfdns.utils.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * apitoken拦截器
 * 登录检查
 * 1.配置到拦截器要拦截哪些请求
 * 2.把这些配置放在容器中
 *
 * @author luwc
 * @title ApiTokenInterceptor
 * @description
 * @time 2023/4/21 17:42:57
 * @version: 1.0
 */
@Component
public class ApiTokenInterceptor implements HandlerInterceptor {
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private JwtConfig jwtConfig;

    /**
     * 目标方法执行之前
     * 登录检查写在这里，如果没有登录，就不执行目标方法
     *
     * @param request
     * @param response
     * @param handler
     * @return boolean
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/4/22 08:34:31
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();
        Map<String, String> urlParams = ApiSignUtils.getUrlParams(request);
        // 引必传参数处理
        if (urlParams.getOrDefault("nonce", "").equals("")
                || urlParams.getOrDefault("timestamp", "").equals("")
                || urlParams.getOrDefault("platform", "").equals("")
                || urlParams.getOrDefault("version", "").equals("")) {
            throw new BadException("缺少必要参数!");
        }
        // 请求重复处理
        StringBuilder stringBuilder = new StringBuilder();
        String ukey = stringBuilder.append("request:").append(urlParams.get("nonce")).append(urlParams.get("timestamp")).append(urlParams.get("platform")).toString();
        if (redisUtils.hasKey(ukey)) {
            throw new BadException("重复请求;");
        }
        redisUtils.set(ukey, urlParams.get("nonce"), 10);
        // 接口签名验证
        ApiSignUtils.checkSignature(request, ApiSignUtils.DEFAULT_SECRET_KEY);

        // 不强制登录的接口
        if (StringUtils.containsAnyIgnoreCase(uri, new String[]{"/login", "/test"})) {
            return true;
        }
        String token = request.getHeader(JwtConfig.getHeader());
        System.out.println(token);
        if (token == null || token.equals("")) {
            throw new AuthException(ResultCode.AUTH_TOKEN_NULL);
        }
        String sub = JwtUtils.validateToken(token);
        if (sub == null || sub.equals("")) {
            throw new AuthException(ResultCode.AUTH_ERROR);
        }
        if (!redisUtils.get(Constants.AUTH_API_KEY + sub).equals(token)) {
            throw new AuthException(ResultCode.AUTH_TOKEN_ERROR);
        }
        if (JwtUtils.isNeedUpdate(token)) {
            token = JwtUtils.createToken(sub);
            response.setHeader(JwtConfig.getHeader(), token);
            redisUtils.del(Constants.AUTH_API_KEY + sub);
            redisUtils.set(Constants.AUTH_API_KEY + sub, token, jwtConfig.getExpireTime());
        }
        request.setAttribute("userId", sub);
        return true;
    }

    /**
     * 目标方法执行完成以后
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @return void
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/4/22 08:35:27
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    /**
     * 页面渲染以后
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return void
     * @throws
     * @version 1.0.0
     * @author luwc
     * @time 2023/4/22 08:35:42
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
